import 'dart:io';

import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';

import 'package:get/get.dart';
import 'package:sainbainu/common/utils/loading.dart';
import 'package:sainbainu/common/utils/permission.dart';
import 'package:sainbainu/common/utils/util.dart';
import 'package:sainbainu/common/values/colors.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:path/path.dart' as p;

/// 控制器
class CustomRecorderController {
  late void Function() clear;
}

typedef RecordedCallback = void Function(String path, Duration duration);

/// 面板高度
const double kPanelHeight = 44;

class Recorder extends StatefulWidget {
  /// 完成录音回调
  final RecordedCallback recordedCallback;

  /// 删除录音回调
  final VoidCallback recordRemoveCallback;

  /// 控制器
  final CustomRecorderController controller;

  const Recorder({
    super.key,
    required this.recordedCallback,
    required this.recordRemoveCallback,
    required this.controller,
  });

  @override
  State<Recorder> createState() => _RecorderState();
}

class _RecorderState extends State<Recorder> {
  /// 录音临时保存路径
  Directory? audioTempDir;

  /// 录音
  String? audio;

  /// 录音控制器
  late RecorderController recorderController;

  /// 是否在录音中
  bool isRecording = false;

  /// 录音时长
  String duration = '';

  /// 录音播放控制器
  late PlayerController recoderPlayerController;

  /// 录音文件读取中
  bool audioReading = false;

  /// 是否在播放
  bool isPlaying = false;

  /// 当前播放时长
  String currentPlayDuration = '';

  @override
  void initState() {
    super.initState();

    /// 实现控制器的方法
    widget.controller.clear = clear;

    /// 录音控制器
    recorderController = RecorderController()
      ..updateFrequency = const Duration(milliseconds: 100)
      ..androidEncoder = AndroidEncoder.aac
      ..androidOutputFormat = AndroidOutputFormat.mpeg4
      ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
      ..sampleRate = 44100
      ..onCurrentDuration.listen((Duration d) {
        setState(() {
          duration = Util.toMMSS(d);
        });
      });

    /// 录音播放器
    recoderPlayerController = PlayerController()
      ..onPlayerStateChanged.listen((playerState) {
        bool playFlag = false;
        if (playerState == PlayerState.playing) {
          playFlag = true;
        } else if (playerState == PlayerState.paused) {
          playFlag = false;
        } else if (playerState == PlayerState.stopped) {
          playFlag = false;
        }
        if (mounted) {
          setState(() {
            isPlaying = playFlag;
          });
        }
      })
      ..onCurrentDurationChanged.listen((currentDuration) {
        /// 监听播放时长
        int remainder = recoderPlayerController.maxDuration - currentDuration;
        setState(() {
          currentPlayDuration = Util.toMMSS(Duration(milliseconds: remainder));
        });
      });
  }

  @override
  void dispose() {
    recorderController.dispose();
    recoderPlayerController.dispose();
    super.dispose();
  }

  /// 清空
  void clear() {
    handleRemoveRecord();
  }

  /// 获取录音保存完整路径
  Future<String> getRecordSavePath() async {
    // getApplicationDocumentsDirectory
    audioTempDir ??= await getTemporaryDirectory();
    return p.join(audioTempDir!.absolute.path,
        'record_${Util.generateRandomString()}.m4a');
  }

  /// 开始、结束录音
  void handleToggleRecord() async {
    if (!isRecording) {
      PermissionStatus status = await Permission.microphone.status;
      if (!status.isGranted) {
        var results = await PermissionUtil.reqPermissions(
          permissions: [Permission.microphone],
          displayRationale: true,
        );
        PermissionStatus status = results[Permission.microphone]!;
        if (!status.isGranted) return;
      }
      recorderController.record(path: await getRecordSavePath());
      setState(() {
        isRecording = true;
      });
    } else {
      String? path = await recorderController.stop();
      if (path != null) {
        setState(() {
          audio = path;
        });
        widget.recordedCallback(
          audio!,
          recorderController.recordedDuration,
        );
        handlePreparePlayer(path);
      }
      setState(() {
        isRecording = false;
        duration = '';
      });
    }
  }

  /// 重新录音
  void handleRefreshRecord() async {
    if (isRecording) {
      await recorderController.stop();
      recorderController.reset(); // 重置波形
      recorderController.refresh(); // 初始化波形
      setState(() {
        duration = '';
      });
      await recorderController.record(path: await getRecordSavePath());
    }
  }

  /// 准备播放器
  void handlePreparePlayer(String path) async {
    try {
      setState(() {
        audioReading = true;
      });
      await recoderPlayerController.preparePlayer(
        path: path,
      );
      currentPlayDuration = Util.toMMSS(
        Duration(milliseconds: recoderPlayerController.maxDuration),
      );
    } catch (e) {
      LoadingUtil.showError('初始化录音文件失败'.tr);
      audio = null;
    } finally {
      audioReading = false;
      setState(() {});
    }
  }

  /// 播放或暂停
  void handlePlayOrPuaseRecord() {
    if (isPlaying) {
      recoderPlayerController.pausePlayer();
    } else {
      recoderPlayerController.startPlayer(
        finishMode: FinishMode.pause,
        forceRefresh: false,
      );
    }
  }

  /// 删除录音
  void handleRemoveRecord() async {
    if (isPlaying) {
      await recoderPlayerController.pausePlayer();
    }
    recoderPlayerController.stopPlayer();
    setState(() {
      audio = null;
    });
    widget.recordRemoveCallback();
  }

  @override
  Widget build(BuildContext context) {
    if (audio != null) {
      return Container(
        height: kPanelHeight,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(6),
        ),
        child: audioReading
            ? _buildPlayerReadyCircularProgress()
            : _buildRecordPlayer(),
      );
    }
    return Container(
      height: kPanelHeight,
      width: double.infinity,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(6),
      ),
      child: isRecording ? _buildRecordingPanel() : _buildRecordButton(),
    );
  }

  /// 录音播放器加载进度条
  Widget _buildPlayerReadyCircularProgress() {
    return Align(
      child: SizedBox(
        width: 20,
        height: 20,
        child: CircularProgressIndicator(
          backgroundColor: Colors.grey[200],
          valueColor: const AlwaysStoppedAnimation(AppColors.success),
          strokeWidth: 2,
        ),
      ),
    );
  }

  /// 录音播放器
  Widget _buildRecordPlayer() {
    return Row(
      children: [
        SizedBox(
          width: 60,
          child: Text(
            currentPlayDuration.isNotEmpty ? currentPlayDuration : '00:00',
            maxLines: 1,
            overflow: TextOverflow.clip,
            style: const TextStyle(fontSize: 12),
            textAlign: TextAlign.center,
          ),
        ),
        Expanded(
          child: LayoutBuilder(builder: (context, constraint) {
            return AudioFileWaveforms(
              size: Size(constraint.maxWidth, 40.0),
              playerController: recoderPlayerController,
              enableSeekGesture: false,
              playerWaveStyle: PlayerWaveStyle(
                fixedWaveColor: AppColors.success.withOpacity(0.3),
                liveWaveColor: AppColors.success,
                seekLineColor: Colors.amber,
                seekLineThickness: 1,
              ),
            );
          }),
        ),
        IconButton(
          style: IconButton.styleFrom(
            backgroundColor: Colors.transparent,
            foregroundColor: AppColors.danger,
            elevation: 0,
            enableFeedback: true,
          ),
          onPressed: () => handleRemoveRecord(),
          icon: const Icon(Icons.cancel_rounded),
        ),
        IconButton(
          style: IconButton.styleFrom(
            backgroundColor: Colors.transparent,
            foregroundColor: AppColors.primary,
            elevation: 0,
            enableFeedback: true,
          ),
          onPressed: () => handlePlayOrPuaseRecord(),
          icon: isPlaying
              ? const Icon(Icons.pause_circle_rounded)
              : const Icon(Icons.play_circle_rounded),
        ),
      ],
    );
  }

  /// 录音中面板
  Widget _buildRecordingPanel() {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        SizedBox(
          width: 60,
          child: Text(
            duration.isNotEmpty ? duration : '00:00',
            maxLines: 1,
            overflow: TextOverflow.clip,
            style: const TextStyle(fontSize: 12),
            textAlign: TextAlign.center,
          ),
        ),
        Expanded(
          child: LayoutBuilder(builder: (context, constraint) {
            return AudioWaveforms(
              size: Size(constraint.maxWidth, 40.0),
              recorderController: recorderController,
              waveStyle: const WaveStyle(
                waveColor: AppColors.success,
                extendWaveform: true,
                middleLineThickness: 1,
                middleLineColor: Colors.amber,
                scaleFactor: 10,
              ),
            );
          }),
        ),
        IconButton(
          style: IconButton.styleFrom(
            backgroundColor: Colors.transparent,
            foregroundColor: AppColors.primary,
            enableFeedback: true,
          ),
          onPressed: () => handleRefreshRecord(),
          icon: const Icon(Icons.refresh_rounded),
        ),
        IconButton(
          style: IconButton.styleFrom(
            backgroundColor: Colors.transparent,
            foregroundColor: AppColors.danger,
            elevation: 0,
            enableFeedback: true,
          ),
          onPressed: () => handleToggleRecord(),
          icon: const Icon(Icons.stop_circle_rounded),
        ),
      ],
    );
  }

  /// 录音按钮
  Widget _buildRecordButton() {
    return GestureDetector(
      onTap: () => handleToggleRecord(),
      child: Row(
        children: [
          Expanded(
            child: Image.asset(
              'assets/images/input-audio.png',
              width: 24,
              height: 24,
              alignment: Alignment.centerLeft,
            ),
          ),
        ],
      ),
    );
  }
}
